<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>05_components_composing</title>
</head>
<body>

  <div id="example"></div>

  <script type="text/javascript" src="../js/react.development.js"></script>
  <script type="text/javascript" src="../js/react-dom.development.js"></script>
  <script type="text/javascript" src="../js/prop-types.js"></script>
  <script type="text/javascript" src="../js/babel.min.js"></script>
  <script type="text/babel">

    /*
    问题: 数据保存在哪个组件内?
        看数据是某个组件需要(给它), 还是某些组件需要(给共同的父组件)
    问题2: 需要在子组件中改变父组件的状态
        子组件中不能直接改变父组件的状态
        状态在哪个组件, 更新状态的行为就应该定义在哪个组件
        解决: 父组件定义函数, 传递给子组件, 子组件调用
    组件化编写功能的流程
      1. 拆分组件
      2. 实现静态组件(只有静态界面, 没有动态数据和交互)
      3. 实现动态组件
        1). 实现初始化数据动态显示
        2). 实现交互功能
    */
    class App extends React.Component {

      constructor(props) {
        super(props)
        // 初始化状态
        this.state = {
          todos: ['吃饭', '睡觉', '打代码']
        }

        this.addTodo = this.addTodo.bind(this)
      }

      addTodo (todo) {
        // this.state.todos.unshift(todo)  // 不能这么做
        const {todos} = this.state
        todos.unshift(todo)
        // 更新状态
        this.setState({todos})
      }

      render () {
        const {todos} = this.state
        return (
          <div>
            <h1>Simple TODO List</h1>
            <Add count={todos.length} addTodo={this.addTodo}/>
            <List todos={todos}/>
          </div>
        )
      }
    }

    class Add extends React.Component {

      constructor (props) {
        super(props)

        this.add = this.add.bind(this)
      }

      add () {
        // 1. 读取输入的数据
        const todo = this.todoInput.value.trim()
        // 2. 检查合法性
        if(!todo) {
          return
        }
        // 3. 添加
        this.props.addTodo(todo)
        // 4. 清除输入
        this.todoInput.value = ''

      }

      render () {
        return (
          <div>
            <input type="text" ref={input => this.todoInput=input}/>
            <button onClick={this.add}>add #{this.props.count+1}</button>
          </div>
        )
      }
    }
    Add.propTypes = {
      count: PropTypes.number.isRequired,
      addTodo: PropTypes.func.isRequired
    }

    class List extends React.Component {

      render () {
        const {todos} = this.props
        return (
          <ul>
            {
              todos.map((todo, index) => {return <li key={index}>{todo}</li>})
            }
          </ul>
        )
      }
    }
    List.propTypes = {
      todos: PropTypes.array.isRequired
    }
    
    ReactDOM.render(<App />, document.getElementById('example'))
  </script>
</body>
</html>
